

# 1、位置参数：实参默认按位置顺序传递，需要个数和形参匹配。按位置传递的参数
# 定义一个函数，传递2个数字，输出最大值
def compare(x, y): # x和y代表函数的形参
    print(x if x > y else y)
# 常规函数的形参和实参叫做：位置参数
# 位置参数：形参和实参数量要一致
# 不能多也不能少，有多少个形参就需要传递多少个实参

# 2、关键字参数：通过指定形参名字来传递参数
def func(x, y, z):
    print(f"x:{x},y:{y},z:{z}")
# 位置参数传递实参
# func(1, 2, 3)
# 关键字参数传递实参（关键字：形参名字）
# func(z=6, x=8, y=4)
# func(6, x=8, y=4) # 注意：位置参数可以结合关键字参数使用，但是不能重复传递实参
# func(z=8, y=4, 6) # 位置参数必须放在关键字参数的前面
func(1, z=8, y=4)
# 通过位置参数和关键字参数结合使用的时候形参和实参数量保持一致

# 3、默认参数：有的参数不是必填，可以给一个默认值
# 如果形参设置了默认值，那么必须在函数定义的时候在所有形参的最后面
def func(x=666, y=111, z=222):
    print(f"x:{x}, y:{y}, z:{z}")

# 当调用函数的时候传递了实参，那么就会覆盖默认参数的值
func()  # 不传递实参，就使用默认形参值
func(1, 2, 3)
# 当函数有默认值的时候，可以传递实参，也可以不传递
# func(1)
# func(1, 2)
# func(1, 2, 3)

# 4、不定长位置参数
'''
可以实现函数接收不确定的实参数量
在使用不定长位置参数
- 传递0个实参
- 传递1个实参
- 传递N个实参
当不定长位置参数接收到实参之后，每一个实参都是元组中的一个元素
所有的不定长参数被接收之后保存在元组中，每一个实参是元组的元素
使用语法格式：在定义函数的时候形参使用*args来进行接收实参
'''
def func(*args):
    print(args) # ()
    print(type(args)) # <class 'tuple'>

func()
func(1, 2, 3, 4, 5, 6)
# 位置参数结合不定长的位置参数
# def func(a, b, c=8, *args):
# 当位置参数结合不定长位置参数和默认参数使用的时候，默认参数需要放置不定长位置参数的前面
# 因为如果放置不定长位置参数后面，那么一直会使用默认值，接收不到具体的实参覆盖默认值
# 只有使用关键字参数指定传递实参给默认参数才能进行覆盖
def func(a, b, *args, c=8):
    print(f"a:{a},b:{b}")
    print(c)
    print(args) # ()
    # print(type(args)) # <class 'tuple'>
# 可以接收2-无数个实参
func(1, 2)
func(1, 3, 3)
func(1, 2, 3, 4, 5, 6)

# 5、不定长关键字参数
'''
在定义函数的时候可以用**kwargs接收不定长关键字参数
- 传递的关键字实参可以是0个或者无数个
- 传递的关键字实参以字典的数据类型进行保持
即参数名称前一个星号表示将多个参数收集到一个”元组“对象中，两个星号是将多个参数收集到”字典“对象中
'''
# def func(**kwargs):
#   print(kwargs) # {}
#   print(type(kwargs)) # <class 'dict'>

# # 不传递关键字参数
# func()
# # 传递关键字参数
# func(a=1, b=2, c=3, name="多多", age=18)
# # {'a': 1, 'b': 2, 'c': 3, 'name': '多多', 'age': 18}
# 一个函数可以接收任意参数：不定长位置参数结合不定长关键字
def func2(*args, **kwargs):
    print(args) # (1, 2, 3, 4)
    print(kwargs) # {'a': 5, 'b': 6}
func2()
func2(1, 2, 3, 4, a=5, b=6)